#include <jni.h>
#include <string>
#include "AndroidLog.h"
#include "FFmpegCallJava.h"
#include "FFPlayer.h"
#include "PlayStatus.h"


extern "C"
{
#include <assert.h>
}


static JavaVM *javaVM;
FFmpegCallJava *mCallJava = NULL;
FFPlayer *player = NULL;
PlayStatus *playStatus = NULL;
bool isExit;

static void native_init(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
    if (player == NULL) {
        if (mCallJava == NULL) {
            mCallJava = new FFmpegCallJava(javaVM, env, &thiz);
        }

        playStatus = new PlayStatus();
        player = new FFPlayer(mCallJava, playStatus);
    }

}

static void native_setDataSource(JNIEnv *env, jobject thiz, jstring url) {

    if (player == NULL) {
        LOGE("%s\n", "player 未初始化");
        return;
    }
    if (!url) {
        return;
    }
    const char *mUrl = env->GetStringUTFChars(url, 0);

    LOGE("player mUrl %s\n", mUrl);

    player->setDataSource(mUrl);
}

static void native_prepare(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
    player->prepare();

}

static void native_start(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
    player->start();

}

static void native_stop(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
    if (isExit) {
        return;
    }
    isExit = true;
    if (player != NULL) {
        player->stop();
        delete (player);
        if (mCallJava != NULL) {
            delete (mCallJava);
            mCallJava = NULL;
        }
        if (playStatus != NULL) {
            delete (playStatus);
            playStatus = NULL;
        }
    }
    isExit = false;
}

static void native_pause(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
    player->pause();

}

static void native_setVolume(JNIEnv *env, jobject thiz, jint volume) {
    LOGE("%s\n", __func__);
    player->setVolume(volume);

}

static void native_setSpeed(JNIEnv *env, jobject thiz, jfloat speed) {
    LOGE("%s\n", __func__);
    player->setSpeed(speed);

}

static void native_setPitch(JNIEnv *env, jobject thiz, jfloat pitch) {
    LOGE("%s\n", __func__);
    player->setPitch(pitch);

}

static void native_setVolumeMute(JNIEnv *env, jobject thiz, jboolean mute) {
    LOGE("%s\n", __func__);
    player->setVolumeMute(mute);

}

static void native_seek(JNIEnv *env, jobject thiz, jint second) {
    LOGE("%s\n", __func__);
    player->seek(second);

}

static void native_resume(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
    player->resume();

}

static void native_setChannelMute(JNIEnv *env, jobject thiz,jint channel) {
    LOGE("%s\n", __func__);
    player->setMute(channel);

}

static int native_getVolume(JNIEnv *env, jobject thiz) {
    LOGE("%s\n", __func__);
   return player->getCurrentVolume();
}

static const JNINativeMethod nativeMethods[] = {
        {"native_init",          "()V",                   (void *) (native_init)},
        {"native_setDataSource", "(Ljava/lang/String;)V", (void *) (native_setDataSource)},
        {"native_prepare",       "()V",                   (void *) (native_prepare)},
        {"native_start",         "()V",                   (void *) (native_start)},
        {"native_stop",          "()V",                   (void *) (native_stop)},
        {"native_pause",         "()V",                   (void *) (native_pause)},
        {"native_resume",        "()V",                   (void *) (native_resume)},
        {"native_setVolume",     "(I)V",                  (void *) (native_setVolume)},
        {"native_setSpeed",      "(F)V",                  (void *) (native_setSpeed)},
        {"native_setPitch",      "(F)V",                  (void *) (native_setPitch)},
        {"native_setVolumeMute",       "(Z)V",                  (void *) (native_setVolumeMute)},
        {"native_seek",          "(I)V",                  (void *) (native_seek)},
        {"native_setChannelMute",          "(I)V",                  (void *) (native_setChannelMute)},
        {"native_getVolume",          "()I",                  (void *) (native_getVolume)},
};

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    jint result = -1;
    javaVM = vm;
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }

    assert(env != NULL);

    // FindClass returns LocalReference
    // 找到需要动态动态注册的Jni类
    jclass jniClass = env->FindClass("com/example/ffmpegplayer/player/PlayerManager");
    env->RegisterNatives(jniClass, nativeMethods, sizeof(nativeMethods) / sizeof(JNINativeMethod));


    return JNI_VERSION_1_4;

}